package editor;

import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

/**
 * This class is used to represent the input triggers of an event (i.e. what input will cause the event).
 *
 * @author Neil Dickson
 */
public final class InputTrigger {
	private	int[]	key;
	private	int[]	modifiers;

	public static final int		CTRL_KEY_DOWN		=	1;
	public static final int		SHIFT_KEY_DOWN		=	2;
	public static final int		ALT_KEY_DOWN		=	4;

	public static final int		KEY_RELEASE			=	0x80000000;

	public static final int		LEFT_BUTTON			=	0x10000;
	public static final int		MIDDLE_BUTTON		=	0x10001;
	public static final int		RIGHT_BUTTON		=	0x10002;
	public static final int		LEFT_CLICK			=	0x10010;
	public static final int		MIDDLE_CLICK		=	0x10011;
	public static final int		RIGHT_CLICK			=	0x10012;
	public static final int		DOUBLE_LEFT_CLICK	=	0x10020;
	public static final int		DOUBLE_MIDDLE_CLICK	=	0x10021;
	public static final int		DOUBLE_RIGHT_CLICK	=	0x10022;
	public static final int		TRIPLE_LEFT_CLICK	=	0x10030;
	public static final int		TRIPLE_MIDDLE_CLICK	=	0x10031;
	public static final int		TRIPLE_RIGHT_CLICK	=	0x10032;

	private static final int	CLICK_COUNT_SHIFT	=	4;
	private static final int	CLICK_COUNT_MASK	=	0xF0;

	public InputTrigger(int key) {
		this(key,0);
	}
	public InputTrigger(int key,int modifiers) {
		this.key = new int[]{key};
		this.modifiers = new int[]{modifiers};
	}
	public InputTrigger(int[] key,int[] modifiers) {
		this.key = key;
		this.modifiers = modifiers;
	}

	public boolean isTriggered(KeyEvent e) {
		boolean isRelease = (e.getID()==KeyEvent.KEY_RELEASED);
		for (int i=0;i<key.length;++i) {
			if (e.getKeyCode()==key[i] && modifiersMatch(modifiers[i],e) && (isRelease==((modifiers[i]&KEY_RELEASE)!=0))) {
				return true;
			}
		}
		return false;
	}
	public boolean isTriggered(MouseEvent e) {
		boolean isRelease = (e.getID()==MouseEvent.MOUSE_RELEASED) || (e.getID()==MouseEvent.MOUSE_CLICKED);
		for (int i=0;i<key.length;++i) {
			int desiredClickCount = (key[i]&CLICK_COUNT_MASK)>>>CLICK_COUNT_SHIFT;
			// NOTE: For some reason, non-click button presses and releases have click count of 1, instead of 0, though this may not always be the case
			if (modifiersMatch(modifiers[i],e) && (isRelease==((modifiers[i]&KEY_RELEASE)!=0)) && (e.getClickCount()==desiredClickCount || (desiredClickCount==0 && e.getClickCount()==1))) {
				if (e.getButton()==MouseEvent.BUTTON1 && (key[i]&~CLICK_COUNT_MASK)==LEFT_BUTTON) {
					return true;
				}
				else if (e.getButton()==MouseEvent.BUTTON2 && (key[i]&~CLICK_COUNT_MASK)==MIDDLE_BUTTON) {
					return true;
				}
				else if (e.getButton()==MouseEvent.BUTTON3 && (key[i]&~CLICK_COUNT_MASK)==RIGHT_BUTTON) {
					return true;
				}
			}
		}
		return false;
	}

	private boolean modifiersMatch(int modifiers, InputEvent e) {
		return (((modifiers&CTRL_KEY_DOWN)!=0) == e.isControlDown())
				&& (((modifiers&SHIFT_KEY_DOWN)!=0) == e.isShiftDown())
				&& (((modifiers&ALT_KEY_DOWN)!=0) == e.isAltDown());
	}

	public int[] getKey() {
		return key;
	}

	public void setKey(int[] key) {
		this.key = key;
	}

	public int[] getModifiers() {
		return modifiers;
	}

	public void setModifiers(int[] modifiers) {
		this.modifiers = modifiers;
	}

	public void set(int[] key,int[] modifiers) {
		this.key = key;
		this.modifiers = modifiers;
	}

	public void set(int key,int modifiers) {
		this.key = new int[]{key};
		this.modifiers = new int[]{modifiers};
	}
}
